package com.shop.shoppingmall.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.shop.shoppingmall.dao.ShUserDao;
import com.shop.shoppingmall.entity.ShUser;
import com.shop.shoppingmall.service.ShUserService;
import com.shop.shoppingmall.service.ShWalletService;
import com.shop.shoppingmall.util.*;
import com.shop.shoppingmall.util.api.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户表(ShUser)表服务实现类
 *
 * @author makejava
 * @since 2020-09-05 15:25:57
 */
@Service("shUserService")
@Slf4j
@Transactional
public class ShUserServiceImpl implements ShUserService {
    @Resource
    private ShUserDao shUserDao;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ShWalletService shWalletService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ShUser queryById(String id) {
        return this.shUserDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<ShUser> queryAllByLimit(int offset, int limit) {
        return this.shUserDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param shUser 实例对象
     * @return 实例对象
     */
    @Override
    public ShUser insert(ShUser shUser) {
        this.shUserDao.insert(shUser);
        return shUser;
    }

    /**
     * 修改数据
     *
     * @param shUser 实例对象
     * @return 实例对象
     */
    @Override
    public ShUser update(ShUser shUser) {
        this.shUserDao.update(shUser);
        return this.queryById(shUser.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(String id) {
        return this.shUserDao.deleteById(id) > 0;
    }

    /**
     * 用户注册
     * @param jsonObject
     * @return
     */
    @Override
    public Result regist(JSONObject jsonObject) {
        ShUser shUser = JSON.parseObject(jsonObject.toJSONString(), ShUser.class);
        if(shUser.getLoginName() ==null || shUser.getPassWord() == null){
            return Result.error(CommonConstant.SC_INTERNAL_SERVER_ERROR_502,"手机号码或者密码不能为空");
        }
        if(shUserDao.selectLoginName(shUser.getLoginName()) != null){
            return Result.error(CommonConstant.SC_INTERNAL_SERVER_ERROR_501,"该账号已注册");
        }
//        if(!shUser.getSuperiorCode().equals("68996888")){
//            int count = count(shUser.getSuperiorCode());
//            if(count ==4){
//                return Result.error("该邀请码已满员，请更换邀请码进行注册");
//            }
//        }
        String smscode = jsonObject.getString("captcha");
        Object code1 = redisUtil.get(shUser.getLoginName());
        if (!smscode.equals(code1)) {
            return Result.error("手机验证码错误");
        }
        String code = invit();
        shUser.setInvitCode(code);
        SimpleDateFormat format0 = new SimpleDateFormat("yyyy-MM-dd");
        String time = format0.format(new Date().getTime());
        shUser.setBirthday(time);
        String id = UUIDGenerator.generate();
        shUser.setId(id);
        String userName = StrUtil.hide(shUser.getLoginName(),3,7);
        shUser.setUserName(userName);
        String salt = oConvertUtils.randomGen(8);
        shUser.setSalt(salt);
        shUser.setMobile(shUser.getLoginName());
        String passwordEncode = PasswordUtil.encrypt(id, shUser.getPassWord(), salt);
        shUser.setPassWord(passwordEncode);
        shUser.setStatus(CommonConstant.USER_UNFREEZE);
        shWalletService.insertWallet(shUser.getId());
        shUser.setDelFlag(CommonConstant.DEL_FLAG_0);
        shUserDao.insert(shUser);
        return Result.ok("注册成功");
    }
    //查询邀请人数是否已经够4个
    public int count(String code){
        Integer count = shUserDao.selectCount(code);
        return count;
    }
    //生成邀请码
    public String invit(){
        String code = oConvertUtils.randomGen(10);
        ShUser shUser1 = shUserDao.selectBig(code);
        if(shUser1 != null){
            return invit();
        }
        return code;
    }

    //判断用户状态
    @Override
    public Result<?> checkUserIsEffective(ShUser sysUser) {
        Result<?> result = new Result<Object>();
        //情况1：根据用户信息查询，该用户不存在
        if (sysUser == null) {
            result.error500("该用户不存在，请注册");
            return result;
        }
        //情况2：根据用户信息查询，该用户已注销
        if (CommonConstant.DEL_FLAG_1==sysUser.getDelFlag()) {
            result.error500("该用户已注销");
            return result;
        }
        //情况3：根据用户信息查询，该用户已冻结
        if (CommonConstant.USER_FREEZE.equals(sysUser.getStatus())) {
            result.error500("该用户已冻结");
            return result;
        }
        return result;
    }

    /**
     * 用户登录
     * @param map
     * @return
     */
    @Override
    public Result userLogin(Map map) {
        Result<JSONObject> result = new Result<JSONObject>();
        String loginName = (String) map.get("loginName");
        String passWord = (String) map.get("passWord");
        //1. 校验用户是否有效
        ShUser shUser = shUserDao.selectLoginName(loginName);
        result = (Result<JSONObject>) checkUserIsEffective(shUser);
        if(!result.isSuccess()) {
            return result;
        }
        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(shUser.getId(), passWord, shUser.getSalt());
        String syspassword = shUser.getPassWord();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }
        JSONObject obj = new JSONObject();
        //用户登录信息
        obj.put("userInfo", shUser);

        // 生成token
        String token = JwtUtil.sign(loginName, syspassword);
        // 设置超时时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);
        //token 信息
        obj.put("token", token);
        result.setResult(obj);
        result.setSuccess(true);
        result.setCode(200);
        return result;
    }

    /**
     * 对冻结状态进行操作
     * @param
     * @return
     */
    @Override
    public Result updateStatus(String id,String status) {
        //根据id查出该用户的信息
        ShUser user = shUserDao.queryById(id);
        if(user != null){
            if(user.getStatus().equals(status)){
                //修改冻结状态
                return Result.ok("您所传递的状态已是该用户现有状态，暂不需要改动！");
            }else{
                user.setStatus(status);
                shUserDao.update(user);
                return Result.ok("修改成功!");
            }
        }else{
            return Result.error("未查到该用户");
        }

    }
    /**
     * 对该用户进行假删除的操作
     * @param
     * @return
     */
    @Override
    public Result deleteUserDelFlag(String id,String delFlag) {
        //根据id查出该用户的信息
        ShUser user = shUserDao.queryById(id);
        if(user != null){
            if(user.getDelFlag().equals("0")){
                user.setDelFlag(delFlag);
                shUserDao.update(user);
                return Result.ok("删除成功!");
            }
        }
        return Result.error("删除失败!");
    }

    /**
     * 根据实体条件对所有用户进行查询
     * @param map
     * @return
     */
    @Override
    public Result selectUserAll(Map map) {
        Integer pagenum = (Integer) map.get("pagenum");
        Integer pagesize = (Integer) map.get("pagesize");
        PageHelper.startPage(pagenum,pagesize);
        int a = (pagenum-1)*pagesize;
        map.put("offset",a);
        map.put("limit",pagesize);
        List<ShUser> shUsers = shUserDao.queryAll(map);
        Map map1 = new HashMap();
        ShUser shUser = shUserDao.selectCountAll(map);
        map1.put("total", shUser.getSums());
        map1.put("shUsers",shUsers);
        return Result.ok(map1);
    }
    /**
     * 修改密码
     * @param username 登录手机号
     * @param oldpassword 旧密码
     * @param newpassword 新密码
     * @param confirmpassword 确认密码
     * @return
     */
    @Override
    public Result resetPassword(String username, String oldpassword, String newpassword, String confirmpassword) {
        ShUser shUser = shUserDao.selectLoginName(username);
        String passwordEncode = PasswordUtil.encrypt(username, oldpassword, shUser.getSalt());
        if (!shUser.getPassWord().equals(passwordEncode)) {
            return Result.error("旧密码输入错误!");
        }
        if (oConvertUtils.isEmpty(newpassword)) {
            return Result.error("新密码不允许为空!");
        }
        if (!newpassword.equals(confirmpassword)) {
            return Result.error("两次输入密码不一致!");
        }
        String password = PasswordUtil.encrypt(username, newpassword, shUser.getSalt());
        shUser.setPassWord(password);
        shUserDao.update(shUser);
        return Result.ok("密码修改成功!");
    }

    /**
     * 根据用户账号查询用户信息
     * @param request
     * @return
     */
    @Override
    public Result selectShUserByLoginName(HttpServletRequest request) {
        String nameByToken = JwtUtil.getUserNameByToken(request);
        ShUser shUser = shUserDao.findByName(nameByToken);
        if(shUser == null){
            return Result.error("您还未注册，请先注册");
        }
        return Result.ok(shUser);
    }

    /**
     * 用户修改手机号
     * @param request
     * @param loginName
     * @return
     */
    @Override
    public Result updateUserNameMobile(HttpServletRequest request,String loginName,String smscode) {
        String nameByToken = JwtUtil.getUserNameByToken(request);
        ShUser shUser = shUserDao.findByName(nameByToken);
        if(shUser == null){
            return Result.error(CommonConstant.SC_OK_201,"您还未注册或者登录，请先注册或登录");
        }
        Object code1 = redisUtil.get(shUser.getLoginName());
        if (!smscode.equals(code1)) {
            return Result.error("手机验证码错误");
        }
        ShUser shUser1 = shUserDao.findByName(nameByToken);
        if(shUser1 == null){
            shUser.setLoginName(loginName);
            shUser.setMobile(loginName);
            shUserDao.update(shUser);
            return Result.ok("修改成功!");
        }else{
            return Result.error("该手机号已经被注册过");
        }

    }

    /**
     * 重置密码
     * @param shUser
     * @param smscode
     * @param password
     * @return
     */
    @Override
    public Result changePassword(ShUser shUser,String smscode ,String password) {
        Object code1 = redisUtil.get(shUser.getLoginName());
        if (!smscode.equals(code1)) {
            return Result.ok("手机验证码错误");
        }
        String passwordEncode = PasswordUtil.encrypt(shUser.getId(), password, shUser.getSalt());
        shUser.setPassWord(passwordEncode);
        shUserDao.update(shUser);
        return Result.ok("密码重置成功!");
    }

    /**
     *  获取短信验证码
     * @param loginName
     * @param smsmode
     * @return
     */
    @Override
    public Result smsLogin(String loginName,String smsmode) {
        Result<String> result = new Result<String>();
        if(oConvertUtils.isEmpty(loginName)){
            result.setMessage("手机号不允许为空！");
            result.setSuccess(false);
            return result;
        }
        Object object = redisUtil.get(loginName);
        if (object != null) {
            result.setMessage("验证码5分钟内，仍然有效！");
            result.setSuccess(false);
            return result;
        }
        //随机数
        String captcha = RandomUtil.randomNumbers(6);
        JSONObject obj = new JSONObject();
        obj.put("code", captcha);
        try {
//            boolean b = false;
            int b =0;
            //注册模板
            if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) {
                ShUser shUser = shUserDao.selectLoginName(loginName);
                if(shUser!=null) {
                    result.setMessage(" 手机号已经注册，请直接登录！");
                    result.setSuccess(false);
                    return result;
                }
                String content ="验证码"+captcha+"，您正在注册成为新用户，该验证码10分钟内有效。请不要把验证码泄露给其他人。如非本人操作，可不用理会！【馨T网】";
//                b = DySmsHelper.sendSms(loginName, obj, DySmsEnum.REGISTER_TEMPLATE_CODE);
                b=DySmsHelper.sendSMS(loginName,content,"");
            }else {
//                //登录模式，校验用户有效性
//                ShUser shUser = shUserDao.selectLoginName(loginName);
//                result = (Result<String>) checkUserIsEffective(shUser);
//                if(!result.isSuccess()) {
//                    String message = result.getMessage();
//                    if("该用户不存在，请注册".equals(message)){
//                        result.error500("该用户不存在或未绑定手机号");
//                    }
//                    return result;
//                }
                /**
                 * smsmode 短信模板方式  0 .登录模板、1.注册模板、2.忘记密码模板
                 */
                if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
                    //登录模板
                    String content ="验证码"+captcha+"，用于手机登录，10分钟内有效。验证码提供给他人可能导致帐号被盗，请勿泄露，谨防被骗。【馨T网】";
//                    b = DySmsHelper.sendSms(loginName, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
                    b=DySmsHelper.sendSMS(loginName,content,"");
                } else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
                    //忘记密码模板
//                    b = DySmsHelper.sendSms(loginName, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE);
                    String content ="您正在执行忘记密码的操作。您的验证码是【"+captcha+"】。该验证码10分钟内有效。请不要把验证码泄露给其他人。如非本人操作，可不用理会！【馨T网】";
                    b=DySmsHelper.sendSMS(loginName,content,"");
                }else if(CommonConstant.SMS_TPL_TYPE_3.equals(smsmode)){
                    //信息变更模板
//                    b = DySmsHelper.sendSms(loginName, obj, DySmsEnum.CHANGE_VERIFICATION_CODE);
                       String content="您正在执行信息变更的操作。您的验证码是【"+captcha+"】。该验证码10分钟内有效。请不要把验证码泄露给其他人。如非本人操作，可不用理会！【馨T网】";
                       b=DySmsHelper.sendSMS(loginName,content,"");
                }
            }
            if (b < 0) {
                result.setMessage("短信验证码发送失败,请稍后重试");
                result.setSuccess(false);
                return result;
            }else if(b == -5){
                result.setMessage("余额不足，请充值");
                result.setSuccess(false);
                return result;
            }
            else if(b == -9){
                result.setMessage("发送号码为空");
                result.setSuccess(false);
                return result;
            }
            //验证码10分钟内有效
            redisUtil.set(loginName, captcha, 300);
            result.setSuccess(true);

        } catch (Exception e) {
            e.printStackTrace();
            result.error500(" 短信接口未配置，请联系管理员！");
            return result;
        }
        return result;
    }

    @Override
    public Result updateUser(ShUser shUser) {
        //根据id查出该用户的信息
       shUserDao.update(shUser);
        return Result.ok("修改成功");
    }

    /**
     * 传token查询用户所有的信息
     * @param request
     * @return
     */
    @Override
    public Result selectShUserAll(HttpServletRequest request) {
        //通过userId查询出用户名和用户表中的密码盐
        String name = JwtUtil.getUserNameByToken(request);
        ShUser shUser = shUserDao.selectLoginName(name);
        if(shUser == null || name == null){
            return Result.error(CommonConstant.SC_OK_201,"您还未注册或者登录，请先注册或登录");
        }
        return Result.ok(shUser);
    }

    /**
     * 查询用户个人邀请码，及邀请用户的信息
     * @param request
     * @return
     */
    @Override
    public Result selectUserBySuperiorCode(HttpServletRequest request) {
        String name = JwtUtil.getUserNameByToken(request);
        ShUser shUser = shUserDao.selectLoginName(name);
        if(shUser == null || name == null){
            return Result.error(CommonConstant.SC_OK_201,"您还未注册或者登录，请先注册或登录");
        }
        String invitCode = shUser.getInvitCode();
        List<ShUser> shUsers = shUserDao.selectUserBySuperiorCode(invitCode);

        Map<String,Object> map = new HashMap<>();
        map.put("invitCode",invitCode);
        map.put("shUsers",shUsers);
        if(shUsers.size() == 0){
            return Result.error("该用户还没有邀请任何人员！");
        }
        return Result.ok(map);
    }
}
